package com.serookie.config.security;


import com.serookie.entity.SysUser;
import com.serookie.entity.WxUser;
import com.serookie.service.SysUserService;
import com.serookie.service.WxUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    private LogoutHandlerConfig logoutConfig;
    @Autowired
    private JwtAccessDeniedHandler jwtAccessDeniedHandler;
    @Autowired
    private com.serookie.config.security.JwtAuthenticationEntryPoint JwtAuthenticationEntryPoint;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private WxUserService wxUserService;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    @Bean
    protected UserDetailsService userDetailsService() {
        return username -> {
            SysUser sysUser = sysUserService.getSysUserByUsername(username);
            if(sysUser!=null){
                return sysUser;
            }
            return null;
        };
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //不需要登录即可访问的接口
        web.ignoring().antMatchers("/wxLogin",
                "/admin/goods/info/{goodsId}","/admin/category/all",
                "/admin/goods/catGoods/{catId}","/admin/swiper/all",
                "/admin/goods/all","/doLogin","/logout","/doc.html",
                "/webjars/**","/swagger-resources/**","/v2/api-docs/**",
                "/vercode","/admin/goods/upload","/admin/upload",
                "/admin/swiper/all","/admin/swiper/upload","/admin/goods/info");
    }
//   角色继承
    @Bean
    RoleHierarchy roleHierarchy(){
        RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
        hierarchy.setHierarchy("ROLE_admin > ROLE_user");
        return hierarchy;
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        关闭cors
        http.cors().and().csrf().disable()
                .authorizeRequests()
                //设置规则，所有的admin接口都要具备admin角色 才能访问
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/wx/**").hasRole("user")
                //所有的接口都必须验证
                .anyRequest().authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .headers()
                .cacheControl();
        //自定义jwt的拦截器
        http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        //添加自定义未登录未授权的结构返回
        http.exceptionHandling().accessDeniedHandler(jwtAccessDeniedHandler).authenticationEntryPoint(JwtAuthenticationEntryPoint);
    }

    @Bean
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){
        return new JwtAuthenticationTokenFilter();
    }
}
